#!/bin/sh

. "$SPEC_PATH/abstract/dbops-restart"

e2e_test_install() {
  CLUSTER_NEAR_NAMESPACE="$CLUSTER_NAMESPACE-near"
  CLUSTER_NEAR_NAME="$(get_sgcluster_name "$CLUSTER_NAME"-near)"
  CLUSTER_FAR_NAMESPACE="$CLUSTER_NAMESPACE-far"
  CLUSTER_FAR_NAME="$(get_sgcluster_name "$CLUSTER_NAME"-far)"
  DBOPS_NAME="$(get_sgdbops_name restart)"

  install_etcd

  kubectl create namespace "$CLUSTER_NAMESPACE"
  kubectl create namespace "$CLUSTER_NEAR_NAMESPACE"
  kubectl create namespace "$CLUSTER_FAR_NAMESPACE"

  deploy_curl_pod "$CLUSTER_NAMESPACE"

  wait_pods_running "$CLUSTER_NAMESPACE" 1
}

e2e_test_uninstall() {
  helm_cleanup_chart "$CLUSTER_FAR_NAME" "$CLUSTER_FAR_NAMESPACE"
  helm_cleanup_chart "$CLUSTER_NEAR_NAME" "$CLUSTER_NEAR_NAMESPACE"

  k8s_async_cleanup_namespace "$CLUSTER_NAMESPACE"
  k8s_async_cleanup_namespace "$CLUSTER_FAR_NAMESPACE"
  k8s_async_cleanup_namespace "$CLUSTER_NEAR_NAMESPACE"
  k8s_async_cleanup_namespace "$(etcd_namespace)"
}

e2e_test_extra_hash() {
  "$SHELL" "$PROJECT_PATH/stackgres-k8s/ci/build/build-functions.sh" path_hash \
    "$(realpath --relative-to "$PROJECT_PATH" "$SPEC_PATH/abstract/dbops-restart")"
}

e2e_test() {
  run_test "Checking that external dcs can be used" check_external_dcs_is_working

  run_test "Checking that external dcs can be used between two clusters" check_external_dcs_two_clusters_is_working

  run_test "Checking that restart is working when etcd is used between two clusters" check_restart_is_working_with_external_dcs

  run_test "Checking that restart is working when etcd is used between two clusters and primary part of the other cluster" check_restart_is_working_with_external_dcs_and_primary_part_of_another_cluster
}

check_external_dcs_is_working() {
  local EXIT_CODE RESULT
  create_or_replace_cluster "$CLUSTER_NEAR_NAME" "$CLUSTER_NEAR_NAMESPACE" 2 \
    --set instanceProfiles[0].name=size-s \
    --set instanceProfiles[0].cpu=250m \
    --set instanceProfiles[0].memory=512Mi \
    --set-string cluster.configurations.patroni.initialConfig.scope=test \
    --set-string cluster.configurations.patroni.initialConfig.etcd3.host=etcd."$(etcd_namespace)" \
    --set-string cluster.configurations.patroni.initialConfig.etcd3.username=root \
    --set-string cluster.configurations.patroni.initialConfig.etcd3.password=test

  wait_pods_running "$CLUSTER_NEAR_NAMESPACE" 2
  wait_cluster_external_dcs "$CLUSTER_NEAR_NAME" "$CLUSTER_NEAR_NAMESPACE" test

  CLUSTER_NAMESPACE="$CLUSTER_NEAR_NAMESPACE" CLUSTER_HOST=test try_function generate_mock_data "$CLUSTER_NEAR_NAME"
  if "$RESULT"
  then
    success "Cluster using external DCS was able to write some data on primary service"
  else
    fail "Cluster using external DCS was not able to write some data on primary service"
  fi
  CLUSTER_NAMESPACE="$CLUSTER_NEAR_NAMESPACE" CLUSTER_HOST=test try_function check_mock_data_samehost "$CLUSTER_NEAR_NAME"
  if "$RESULT"
  then
    success "Cluster using external DCS was able to read some data from primary service"
  else
    fail "Cluster using external DCS was not able to read some data from primary service"
  fi
  CLUSTER_NAMESPACE="$CLUSTER_NEAR_NAMESPACE" CLUSTER_HOST=test try_function check_mock_data_replication "$CLUSTER_NEAR_NAME"
  if "$RESULT"
  then
    success "Cluster using external DCS was able to read some data from replicas service"
  else
    fail "Cluster using external DCS was not able to read some data from replicas service"
  fi
}

check_external_dcs_two_clusters_is_working() {
  local EXIT_CODE RESULT
  kubectl get secret -n "$CLUSTER_NEAR_NAMESPACE" "$CLUSTER_NEAR_NAME" -o json \
    | jq "del(.metadata.ownerReferences) | .metadata.namespace = \"$CLUSTER_FAR_NAMESPACE\"" \
    | kubectl create -f -
  create_or_replace_cluster "$CLUSTER_FAR_NAME" "$CLUSTER_FAR_NAMESPACE" 2 \
    --set instanceProfiles[0].name=size-s \
    --set instanceProfiles[0].cpu=250m \
    --set instanceProfiles[0].memory=512Mi \
    --set credentials=null \
    --set-string cluster.configurations.credentials.users.superuser.username.name="$CLUSTER_NEAR_NAME" \
    --set-string cluster.configurations.credentials.users.superuser.username.key="superuser-username" \
    --set-string cluster.configurations.credentials.users.superuser.password.name="$CLUSTER_NEAR_NAME" \
    --set-string cluster.configurations.credentials.users.superuser.password.key="superuser-password" \
    --set-string cluster.configurations.credentials.users.replication.username.name="$CLUSTER_NEAR_NAME" \
    --set-string cluster.configurations.credentials.users.replication.username.key="replication-username" \
    --set-string cluster.configurations.credentials.users.replication.password.name="$CLUSTER_NEAR_NAME" \
    --set-string cluster.configurations.credentials.users.replication.password.key="replication-password" \
    --set-string cluster.configurations.credentials.users.authenticator.username.name="$CLUSTER_NEAR_NAME" \
    --set-string cluster.configurations.credentials.users.authenticator.username.key="authenticator-username" \
    --set-string cluster.configurations.credentials.users.authenticator.password.name="$CLUSTER_NEAR_NAME" \
    --set-string cluster.configurations.credentials.users.authenticator.password.key="authenticator-password" \
    --set-string cluster.configurations.patroni.initialConfig.scope=test \
    --set-string cluster.configurations.patroni.initialConfig.etcd3.host=etcd."$(etcd_namespace)" \
    --set-string cluster.configurations.patroni.initialConfig.etcd3.username=root \
    --set-string cluster.configurations.patroni.initialConfig.etcd3.password=test

  wait_pods_running "$CLUSTER_FAR_NAMESPACE" 2
  wait_cluster_external_dcs "$CLUSTER_FAR_NAME" "$CLUSTER_FAR_NAMESPACE" test false

  CLUSTER_NAMESPACE="$CLUSTER_FAR_NAMESPACE" CLUSTER_NAME="$CLUSTER_FAR_NAME" CLUSTER_HOST="$CLUSTER_FAR_NAME-replicas" try_function wait_until check_mock_data_samehost "$CLUSTER_FAR_NAME"
  if "$RESULT"
  then
    success "Cluster using external DCS is replicating from cluster using same DCS and scope and was able to read some data from replicas service"
  else
    fail "Cluster using external DCS is not replicating from cluster using same DCS and scope or was not able to read some data from replicas service"
  fi
}

check_restart_is_working_with_external_dcs() {
  CLUSTER_NAMESPACE="$CLUSTER_NEAR_NAMESPACE" CLUSTER_NAME="$CLUSTER_NEAR_NAME" set_restarted_pods
  CLUSTER_NAMESPACE="$CLUSTER_NEAR_NAMESPACE" CLUSTER_NAME="$CLUSTER_NEAR_NAME" trigger_cluster_require_restart

  cat << EOF | kubectl create -f -
apiVersion: stackgres.io/v1
kind: SGDbOps
metadata:
  name: $DBOPS_NAME
  namespace: $CLUSTER_NEAR_NAMESPACE
spec:
  sgCluster: $CLUSTER_NEAR_NAME
  op: restart
  restart:
    method: InPlace
EOF

  wait_until eval '[ "$(kubectl get sgdbops -n "$CLUSTER_NEAR_NAMESPACE" "$DBOPS_NAME" \
    --template "{{ .status.opRetries }}")" = "0" ]'
  kubectl get sgdbops -n "$CLUSTER_NEAR_NAMESPACE" "$DBOPS_NAME" -o yaml > "$LOG_PATH/sgdbops-near.yaml"
  kubectl delete sgdbops -n "$CLUSTER_NEAR_NAMESPACE" "$DBOPS_NAME"
  kubectl create -f "$LOG_PATH/sgdbops-near.yaml"

  CLUSTER_NAMESPACE="$CLUSTER_NEAR_NAMESPACE" CLUSTER_NAME="$CLUSTER_NEAR_NAME" CLUSTER_HOST=test check_restart

  kubectl delete sgdbops -n "$CLUSTER_NEAR_NAMESPACE" "$DBOPS_NAME"
}

check_restart_is_working_with_external_dcs_and_primary_part_of_another_cluster() {
  CLUSTER_NAMESPACE="$CLUSTER_FAR_NAMESPACE" CLUSTER_NAME="$CLUSTER_FAR_NAME" trigger_cluster_require_restart
  CLUSTER_NAMESPACE="$CLUSTER_FAR_NAMESPACE" CLUSTER_NAME="$CLUSTER_FAR_NAME" set_restarted_pods

  cat << EOF | kubectl create -f -
apiVersion: stackgres.io/v1
kind: SGDbOps
metadata:
  name: $DBOPS_NAME
  namespace: $CLUSTER_FAR_NAMESPACE
spec:
  sgCluster: $CLUSTER_FAR_NAME
  op: restart
  restart:
    method: InPlace
EOF

  wait_until eval '[ "$(kubectl get sgdbops -n "$CLUSTER_FAR_NAMESPACE" "$DBOPS_NAME" \
    --template "{{ .status.opRetries }}")" = "0" ]'
  kubectl get sgdbops -n "$CLUSTER_FAR_NAMESPACE" "$DBOPS_NAME" -o yaml > "$LOG_PATH/sgdbops.yaml"
  kubectl delete sgdbops -n "$CLUSTER_FAR_NAMESPACE" "$DBOPS_NAME"
  kubectl create -f "$LOG_PATH/sgdbops.yaml"

  CLUSTER_NAMESPACE="$CLUSTER_FAR_NAMESPACE" CLUSTER_NAME="$CLUSTER_FAR_NAME" CLUSTER_HOST="$CLUSTER_FAR_NAME-replicas" check_restart

  kubectl delete sgdbops -n "$CLUSTER_FAR_NAMESPACE" "$DBOPS_NAME"
}
